home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / system1.c < prev    next >
C/C++ Source or Header  |  2000-05-04  |  22KB  |  873 lines

  1. /*************************************************************************
  2.  
  3.   System1 / System 2.   By Jarek Parchanski & Mirko Buffoni.
  4.  
  5.   Many thanks to Roberto Ventura, for precious information about
  6.   System 1 hardware.
  7.  
  8. *************************************************************************/
  9.  
  10. #include "system1.h"
  11.  
  12. extern int system1_bank;
  13.  
  14. unsigned char     *system1_scroll_y;
  15. unsigned char     *system1_scroll_x;
  16. unsigned char     *system1_videoram;
  17. unsigned char     *system1_backgroundram;
  18. unsigned char     *system1_sprites_collisionram;
  19. unsigned char     *system1_background_collisionram;
  20. unsigned char     *system1_scrollx_ram;
  21. size_t system1_videoram_size;
  22. size_t system1_backgroundram_size;
  23.  
  24. static unsigned char    *bg_ram;
  25. static unsigned char     *bg_dirtybuffer;
  26. static unsigned char     *tx_dirtybuffer;
  27. static unsigned char     *SpritesCollisionTable;
  28. static int    background_scrollx=0,background_scrolly=0;
  29. static unsigned char bg_bank=0,bg_bank_latch=0;
  30.  
  31. static int        scrollx_row[32];
  32. static struct osd_bitmap *bitmap1;
  33. static struct osd_bitmap *bitmap2;
  34.  
  35. static int  system1_pixel_mode = 0,system1_background_memory,system1_video_mode=0;
  36.  
  37. static unsigned char palette_lookup[256*3];
  38.  
  39.  
  40.  
  41. /***************************************************************************
  42.  
  43.   Convert the color PROMs into a more useable format.
  44.  
  45.   There are two kind of color handling: in the System 1 games, values in the
  46.   palette RAM are directly mapped to colors with the usual BBGGGRRR format;
  47.   in the System 2 ones (Choplifter, WBML, etc.), the value in the palette RAM
  48.   is a lookup offset for three palette PROMs in RRRRGGGGBBBB format.
  49.  
  50.   It's hard to tell for sure because they use resistor packs, but here's
  51.   what I think the values are from measurment with a volt meter:
  52.  
  53.   Blue: .250K ohms
  54.   Blue: .495K ohms
  55.   Green:.250K ohms
  56.   Green:.495K ohms
  57.   Green:.995K ohms
  58.   Red:  .495K ohms
  59.   Red:  .250K ohms
  60.   Red:  .995K ohms
  61.  
  62.   accurate to +/- .003K ohms.
  63.  
  64. ***************************************************************************/
  65. void system1_vh_convert_color_prom(unsigned char *palette, unsigned short *colortable,const unsigned char *color_prom)
  66. {
  67.     int i;
  68.  
  69.     palette = palette_lookup;
  70.  
  71.     if (color_prom)
  72.     {
  73.         for (i = 0;i < 256;i++)
  74.         {
  75.             int bit0,bit1,bit2,bit3;
  76.  
  77.             bit0 = (color_prom[0*256] >> 0) & 0x01;
  78.             bit1 = (color_prom[0*256] >> 1) & 0x01;
  79.             bit2 = (color_prom[0*256] >> 2) & 0x01;
  80.             bit3 = (color_prom[0*256] >> 3) & 0x01;
  81.             *(palette++) = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
  82.             bit0 = (color_prom[1*256] >> 0) & 0x01;
  83.             bit1 = (color_prom[1*256] >> 1) & 0x01;
  84.             bit2 = (color_prom[1*256] >> 2) & 0x01;
  85.             bit3 = (color_prom[1*256] >> 3) & 0x01;
  86.             *(palette++) = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
  87.             bit0 = (color_prom[2*256] >> 0) & 0x01;
  88.             bit1 = (color_prom[2*256] >> 1) & 0x01;
  89.             bit2 = (color_prom[2*256] >> 2) & 0x01;
  90.             bit3 = (color_prom[2*256] >> 3) & 0x01;
  91.             *(palette++) = 0x0e * bit0 + 0x1f * bit1 + 0x43 * bit2 + 0x8f * bit3;
  92.             color_prom++;
  93.         }
  94.     }
  95.     else
  96.     {
  97.         for (i = 0;i < 256;i++)
  98.         {
  99.             int val;
  100.  
  101.             /* red component */
  102.             val = (i >> 0) & 0x07;
  103.             *(palette++) = (val << 5) | (val << 2) | (val >> 1);
  104.             /* green component */
  105.             val = (i >> 3) & 0x07;
  106.             *(palette++) = (val << 5) | (val << 2) | (val >> 1);
  107.             /* blue component */
  108.             val = (i >> 5) & 0x06;
  109.             if (val) val++;
  110.             *(palette++) = (val << 5) | (val << 2) | (val >> 1);
  111.         }
  112.     }
  113. }
  114.  
  115. WRITE_HANDLER( system1_paletteram_w )
  116. {
  117.     unsigned char *palette = palette_lookup + data * 3;
  118.     int r,g,b;
  119.  
  120.  
  121.     paletteram[offset] = data;
  122.  
  123.     r = *palette++;
  124.     g = *palette++;
  125.     b = *palette++;
  126.  
  127.     palette_change_color(offset,r,g,b);
  128. }
  129.  
  130.  
  131.  
  132. int system1_vh_start(void)
  133. {
  134.     if ((SpritesCollisionTable = malloc(256*256)) == 0)
  135.         return 1;
  136.     memset(SpritesCollisionTable,255,256*256);
  137.  
  138.     if ((bg_dirtybuffer = malloc(1024)) == 0)
  139.     {
  140.         free(SpritesCollisionTable);
  141.         return 1;
  142.     }
  143.     memset(bg_dirtybuffer,1,1024);
  144.     if ((tx_dirtybuffer = malloc(1024)) == 0)
  145.     {
  146.         free(bg_dirtybuffer);
  147.         free(SpritesCollisionTable);
  148.         return 1;
  149.     }
  150.     memset(tx_dirtybuffer,1,1024);
  151.     if ((bg_ram = malloc(0x4000)) == 0)            /* Allocate 16k for background banked ram */
  152.     {
  153.         free(bg_dirtybuffer);
  154.         free(tx_dirtybuffer);
  155.         free(SpritesCollisionTable);
  156.         return 1;
  157.     }
  158.     memset(bg_ram,0,0x4000);
  159.     if ((bitmap1 = osd_create_bitmap(Machine->drv->screen_width,Machine->drv->screen_height)) == 0)
  160.     {
  161.         free(bg_ram);
  162.         free(bg_dirtybuffer);
  163.         free(tx_dirtybuffer);
  164.         free(SpritesCollisionTable);
  165.         return 1;
  166.     }
  167.     if ((bitmap2 = osd_create_bitmap(Machine->drv->screen_width,Machine->drv->screen_height)) == 0)
  168.     {
  169.         osd_free_bitmap(bitmap1);
  170.         free(bg_ram);
  171.         free(bg_dirtybuffer);
  172.         free(tx_dirtybuffer);
  173.         free(SpritesCollisionTable);
  174.         return 1;
  175.     }
  176.  
  177.     return 0;
  178. }
  179.  
  180. void system1_vh_stop(void)
  181. {
  182.     osd_free_bitmap(bitmap2);
  183.     osd_free_bitmap(bitmap1);
  184.     free(bg_ram);
  185.     free(bg_dirtybuffer);
  186.     free(tx_dirtybuffer);
  187.     free(SpritesCollisionTable);
  188. }
  189.  
  190. WRITE_HANDLER( system1_videomode_w )
  191. {
  192. if (data & 0xef) logerror("videomode = %02x\n",data);
  193.  
  194.     /* bit 0 is coin counter */
  195.  
  196.     /* bit 3 is ??? */
  197.  
  198.     /* bit 4 is screen blank */
  199.     system1_video_mode = data;
  200. }
  201.  
  202. READ_HANDLER( system1_videomode_r )
  203. {
  204.     return system1_video_mode;
  205. }
  206.  
  207. void system1_define_sprite_pixelmode(int Mode)
  208. {
  209.     system1_pixel_mode = Mode;
  210. }
  211.  
  212. void system1_define_background_memory(int Mode)
  213. {
  214.     system1_background_memory = Mode;
  215. }
  216.  
  217. static int GetSpriteBottomY(int spr_number)
  218. {
  219.     return  spriteram[0x10 * spr_number + SPR_Y_BOTTOM];
  220. }
  221.  
  222.  
  223. static void Pixel(struct osd_bitmap *bitmap,int x,int y,int spr_number,int color)
  224. {
  225.     int xr,yr,spr_y1,spr_y2;
  226.     int SprOnScreen;
  227.  
  228.  
  229.     if (x < Machine->drv->visible_area.min_x ||
  230.         x > Machine->drv->visible_area.max_x ||
  231.         y < Machine->drv->visible_area.min_y ||
  232.         y > Machine->drv->visible_area.max_y)
  233.         return;
  234.  
  235.     if (SpritesCollisionTable[256*y+x] == 255)
  236.     {
  237.         SpritesCollisionTable[256*y+x] = spr_number;
  238.         plot_pixel(bitmap, x, y, color);
  239.     }
  240.     else
  241.     {
  242.         SprOnScreen=SpritesCollisionTable[256*y+x];
  243.         system1_sprites_collisionram[SprOnScreen + 32 * spr_number] = 0xff;
  244.         if (system1_pixel_mode==system1_SPRITE_PIXEL_MODE1)
  245.         {
  246.             spr_y1 = GetSpriteBottomY(spr_number);
  247.             spr_y2 = GetSpriteBottomY(SprOnScreen);
  248.             if (spr_y1 >= spr_y2)
  249.             {
  250.                 plot_pixel(bitmap, x, y, color);
  251.                 SpritesCollisionTable[256*y+x]=spr_number;
  252.             }
  253.         }
  254.         else
  255.         {
  256.             plot_pixel(bitmap, x, y, color);
  257.             SpritesCollisionTable[256*y+x]=spr_number;
  258.         }
  259.     }
  260.  
  261.     xr = ((x - background_scrollx) & 0xff) / 8;
  262.     yr = ((y - background_scrolly) & 0xff) / 8;
  263.  
  264.     /* TODO: bits 5 and 6 of backgroundram are also used (e.g. Pitfall2, Mr. Viking) */
  265.     /* what's the difference? Bit 7 is used in Choplifter/WBML for extra char bank */
  266.     /* selection, but it is also set in Pitfall2 */
  267.  
  268.     if (system1_background_memory == system1_BACKGROUND_MEMORY_SINGLE)
  269.     {
  270.         if (system1_backgroundram[2 * (32 * yr + xr) + 1] & 0x10)
  271.             system1_background_collisionram[0x20 + spr_number] = 0xff;
  272.     }
  273.     else
  274.     {
  275.         /* TODO: I should handle the paged background memory here. */
  276.         /* maybe collision detection is not used by the paged games */
  277.         /* (wbml and tokisens), though tokisens doesn't play very well */
  278.         /* (you can't seem to fit in gaps where you should fit) */
  279.     }
  280.  
  281.     /* TODO: collision should probably be checked with the foreground as well */
  282.     /* (TeddyBoy Blues, head of the tiger in girl bonus round) */
  283. }
  284.  
  285. WRITE_HANDLER( system1_background_collisionram_w )
  286. {
  287.     /* to do the RAM check, Mister Viking writes 0xff and immediately */
  288.     /* reads it back, expecting bit 0 to be NOT set. */
  289.     system1_background_collisionram[offset] = 0x7e;
  290. }
  291.  
  292. WRITE_HANDLER( system1_sprites_collisionram_w )
  293. {
  294.     /* to do the RAM check, Mister Viking write 0xff and immediately */
  295.     /* reads it back, expecting bit 0 to be NOT set. */
  296.     /* Up'n Down expects to find 0x7e at f800 before doing the whole */
  297.     /* collision test */
  298.     system1_sprites_collisionram[offset] = 0x7e;
  299. }
  300.  
  301.  
  302.  
  303. extern struct GameDriver driver_wbml;
  304.  
  305. static void RenderSprite(struct osd_bitmap *bitmap,int spr_number)
  306. {
  307.     int SprX,SprY,Col,Row,Height,src;
  308.     int bank;
  309.     unsigned char *SprReg;
  310.     unsigned short *SprPalette;
  311.     short skip;    /* bytes to skip before drawing each row (can be negative) */
  312.  
  313.  
  314.     SprReg        = spriteram + 0x10 * spr_number;
  315.  
  316.     src = SprReg[SPR_GFXOFS_LO] + (SprReg[SPR_GFXOFS_HI] << 8);
  317.     bank = 0x8000 * (((SprReg[SPR_X_HI] & 0x80) >> 7) + ((SprReg[SPR_X_HI] & 0x40) >> 5));
  318.     bank &= (memory_region_length(REGION_GFX2)-1);    /* limit to the range of available ROMs */
  319.     skip = SprReg[SPR_SKIP_LO] + (SprReg[SPR_SKIP_HI] << 8);
  320.  
  321.     Height        = SprReg[SPR_Y_BOTTOM] - SprReg[SPR_Y_TOP];
  322.     SprPalette    = Machine->remapped_colortable + 0x10 * spr_number;
  323.     SprX = SprReg[SPR_X_LO] + ((SprReg[SPR_X_HI] & 0x01) << 8);
  324.     SprX /= 2;    /* the hardware has sub-pixel placement, it seems */
  325.     if (Machine->gamedrv == &driver_wbml || Machine->gamedrv->clone_of == &driver_wbml)
  326.         SprX += 7;
  327.     SprY = SprReg[SPR_Y_TOP] + 1;
  328.  
  329.     for (Row = 0;Row < Height;Row++)
  330.     {
  331.         src += skip;
  332.  
  333.         Col = 0;
  334.         while (Col < 256)    /* this is only a safety check, */
  335.                             /* drawing is stopped by color == 15 */
  336.         {
  337.             int color1,color2;
  338.  
  339.             if (src & 0x8000)    /* flip x */
  340.             {
  341.                 int offs,data;
  342.  
  343.                 offs = ((src - Col / 2) & 0x7fff) + bank;
  344.  
  345.                 /* memory region #2 contains the packed sprite data */
  346.                 data = memory_region(REGION_GFX2)[offs];
  347.                 color1 = data & 0x0f;
  348.                 color2 = data >> 4;
  349.             }
  350.             else
  351.             {
  352.                 int offs,data;
  353.  
  354.                 offs = ((src + Col / 2) & 0x7fff) + bank;
  355.  
  356.                 /* memory region #2 contains the packed sprite data */
  357.                 data = memory_region(REGION_GFX2)[offs];
  358.                 color1 = data >> 4;
  359.                 color2 = data & 0x0f;
  360.             }
  361.  
  362.             if (color1 == 15) break;
  363.             if (color1)
  364.                 Pixel(bitmap,SprX+Col,SprY+Row,spr_number,SprPalette[color1]);
  365.  
  366.             Col++;
  367.  
  368.             if (color2 == 15) break;
  369.             if (color2)
  370.                 Pixel(bitmap,SprX+Col,SprY+Row,spr_number,SprPalette[color2]);
  371.  
  372.             Col++;
  373.         }
  374.     }
  375. }
  376.  
  377.  
  378. static void DrawSprites(struct osd_bitmap *bitmap)
  379. {
  380.     int spr_number,SprBottom,SprTop;
  381.     unsigned char *SprReg;
  382.  
  383.  
  384.     memset(SpritesCollisionTable,255,256*256);
  385.  
  386.     for (spr_number = 0;spr_number < 32;spr_number++)
  387.     {
  388.         SprReg         = spriteram + 0x10 * spr_number;
  389.         SprTop        = SprReg[SPR_Y_TOP];
  390.         SprBottom    = SprReg[SPR_Y_BOTTOM];
  391.         if (SprBottom && (SprBottom-SprTop > 0))
  392.             RenderSprite(bitmap,spr_number);
  393.     }
  394. }
  395.  
  396.  
  397.  
  398. void system1_compute_palette (void)
  399. {
  400.     unsigned char bg_usage[64], tx_usage[64], sp_usage[32];
  401.     int i;
  402.  
  403.     memset (bg_usage, 0, sizeof (bg_usage));
  404.     memset (tx_usage, 0, sizeof (tx_usage));
  405.     memset (sp_usage, 0, sizeof (sp_usage));
  406.  
  407.     for (i = 0; i<system1_backgroundram_size; i+=2)
  408.     {
  409.         int code = (system1_backgroundram[i] + (system1_backgroundram[i+1] << 8)) & 0x7FF;
  410.         int palette = code >> 5;
  411.         bg_usage[palette & 0x3f] = 1;
  412.     }
  413.  
  414.     for (i = 0; i<system1_videoram_size; i+=2)
  415.     {
  416.         int code = (system1_videoram[i] + (system1_videoram[i+1] << 8)) & 0x7FF;
  417.  
  418.         if (code)
  419.         {
  420.             int palette = code>>5;
  421.             tx_usage[palette & 0x3f] = 1;
  422.         }
  423.     }
  424.  
  425.     for (i=0; i<32; i++)
  426.     {
  427.         unsigned char *reg;
  428.         int top, bottom;
  429.  
  430.         reg     = spriteram + 0x10 * i;
  431.         top        = reg[SPR_Y_TOP];
  432.         bottom    = reg[SPR_Y_BOTTOM];
  433.         if (bottom && (bottom - top > 0))
  434.             sp_usage[i] = 1;
  435.     }
  436.  
  437.     for (i = 0; i < 64; i++)
  438.     {
  439.         if (bg_usage[i])
  440.             memset (palette_used_colors + 1024 + i * 8, PALETTE_COLOR_USED, 8);
  441.         else
  442.             memset (palette_used_colors + 1024 + i * 8, PALETTE_COLOR_UNUSED, 8);
  443.  
  444.         palette_used_colors[512 + i * 8] = PALETTE_COLOR_TRANSPARENT;
  445.         if (tx_usage[i])
  446.             memset (palette_used_colors + 512 + i * 8 + 1, PALETTE_COLOR_USED, 7);
  447.         else
  448.             memset (palette_used_colors + 512 + i * 8 + 1, PALETTE_COLOR_UNUSED, 7);
  449.     }
  450.  
  451.     for (i = 0; i < 32; i++)
  452.     {
  453.         palette_used_colors[0 + i * 16] = PALETTE_COLOR_TRANSPARENT;
  454.         if (sp_usage[i])
  455.             memset (palette_used_colors + 0 + i * 16 + 1, PALETTE_COLOR_USED, 15);
  456.         else
  457.             memset (palette_used_colors + 0 + i * 16 + 1, PALETTE_COLOR_UNUSED, 15);
  458.     }
  459.  
  460.     if (palette_recalc ())
  461.     {
  462.         memset(bg_dirtybuffer,1,1024);
  463.         memset(tx_dirtybuffer,1,1024);
  464.     }
  465. }
  466.  
  467.  
  468. WRITE_HANDLER( system1_videoram_w )
  469. {
  470.     system1_videoram[offset] = data;
  471.     tx_dirtybuffer[offset>>1] = 1;
  472. }
  473.  
  474. WRITE_HANDLER( system1_backgroundram_w )
  475. {
  476.     system1_backgroundram[offset] = data;
  477.     bg_dirtybuffer[offset>>1] = 1;
  478. }
  479.  
  480.  
  481. static int system1_draw_fg(struct osd_bitmap *bitmap,int priority)
  482. {
  483.     int sx,sy,offs;
  484.     int drawn = 0;
  485.  
  486.  
  487.     priority <<= 3;
  488.  
  489.     for (offs = 0;offs < system1_videoram_size;offs += 2)
  490.     {
  491.         if ((system1_videoram[offs+1] & 0x08) == priority)
  492.         {
  493.             int code,color;
  494.  
  495.  
  496.             code = (system1_videoram[offs] | (system1_videoram[offs+1] << 8));
  497.             code = ((code >> 4) & 0x800) | (code & 0x7ff);    /* Heavy Metal only */
  498.             color = ((code >> 5) & 0x3f);
  499.             sx = (offs/2) % 32;
  500.             sy = (offs/2) / 32;
  501.  
  502.             if (Machine->gfx[0]->pen_usage[code] & ~1)
  503.             {
  504.                 drawn = 1;
  505.  
  506.                 drawgfx(bitmap,Machine->gfx[0],
  507.                         code,
  508.                         color,
  509.                         0,0,
  510.                         8*sx,8*sy,
  511.                         &Machine->drv->visible_area,TRANSPARENCY_PEN,0);
  512.             }
  513.         }
  514.     }
  515.  
  516.     return drawn;
  517. }
  518.  
  519. static void system1_draw_bg(struct osd_bitmap *bitmap,int priority)
  520. {
  521.     int sx,sy,offs;
  522.  
  523.  
  524.     background_scrollx = ((system1_scroll_x[0] >> 1) + ((system1_scroll_x[1] & 1) << 7) + 14) & 0xff;
  525.     background_scrolly = (-*system1_scroll_y) & 0xff;
  526.  
  527.     if (priority == -1)
  528.     {
  529.         /* optimized far background */
  530.  
  531.         /* for every character in the background video RAM, check if it has
  532.          * been modified since last time and update it accordingly.
  533.          */
  534.  
  535.         for (offs = 0;offs < system1_backgroundram_size;offs += 2)
  536.         {
  537.             if (bg_dirtybuffer[offs / 2])
  538.             {
  539.                 int code,color;
  540.  
  541.  
  542.                 bg_dirtybuffer[offs / 2] = 0;
  543.  
  544.                 code = (system1_backgroundram[offs] | (system1_backgroundram[offs+1] << 8));
  545.                 code = ((code >> 4) & 0x800) | (code & 0x7ff);    /* Heavy Metal only */
  546.                 color = ((code >> 5) & 0x3f) + 0x40;
  547.                 sx = (offs/2) % 32;
  548.                 sy = (offs/2) / 32;
  549.  
  550.                 drawgfx(bitmap1,Machine->gfx[0],
  551.                         code,
  552.                         color,
  553.                         0,0,
  554.                         8*sx,8*sy,
  555.                         0,TRANSPARENCY_NONE,0);
  556.             }
  557.         }
  558.  
  559.         /* copy the temporary bitmap to the screen */
  560.         copyscrollbitmap(bitmap,bitmap1,1,&background_scrollx,1,&background_scrolly,&Machine->drv->visible_area,TRANSPARENCY_NONE,0);
  561.     }
  562.     else
  563.     {
  564.         priority <<= 3;
  565.  
  566.         for (offs = 0;offs < system1_backgroundram_size;offs += 2)
  567.         {
  568.             if ((system1_backgroundram[offs+1] & 0x08) == priority)
  569.             {
  570.                 int code,color;
  571.  
  572.  
  573.                 code = (system1_backgroundram[offs] | (system1_backgroundram[offs+1] << 8));
  574.                 code = ((code >> 4) & 0x800) | (code & 0x7ff);    /* Heavy Metal only */
  575.                 color = ((code >> 5) & 0x3f) + 0x40;
  576.                 sx = (offs/2) % 32;
  577.                 sy = (offs/2) / 32;
  578.  
  579.                 sx = 8*sx + background_scrollx;
  580.                 sy = 8*sy + background_scrolly;
  581.  
  582.                 drawgfx(bitmap,Machine->gfx[0],
  583.                         code,
  584.                         color,
  585.                         0,0,
  586.                         sx,sy,
  587.                         &Machine->drv->visible_area,TRANSPARENCY_PEN,0);
  588.                 if (sx > 248)
  589.                     drawgfx(bitmap,Machine->gfx[0],
  590.                             code,
  591.                             color,
  592.                             0,0,
  593.                             sx-256,sy,
  594.                             &Machine->drv->visible_area,TRANSPARENCY_PEN,0);
  595.                 if (sy > 248)
  596.                 {
  597.                     drawgfx(bitmap,Machine->gfx[0],
  598.                             code,
  599.                             color,
  600.                             0,0,
  601.                             sx,sy-256,
  602.                             &Machine->drv->visible_area,TRANSPARENCY_PEN,0);
  603.                     if (sx > 248)
  604.                         drawgfx(bitmap,Machine->gfx[0],
  605.                                 code,
  606.                                 color,
  607.                                 0,0,
  608.                                 sx-256,sy-256,
  609.                                 &Machine->drv->visible_area,TRANSPARENCY_PEN,0);
  610.                 }
  611.             }
  612.         }
  613.     }
  614. }
  615.  
  616. void system1_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
  617. {
  618.     int drawn;
  619.  
  620.  
  621.     system1_compute_palette();
  622.  
  623.     system1_draw_bg(bitmap,-1);
  624.     drawn = system1_draw_fg(bitmap,0);
  625.     /* redraw low priority bg tiles if necessary */
  626.     if (drawn) system1_draw_bg(bitmap,0);
  627.     DrawSprites(bitmap);
  628.     system1_draw_bg(bitmap,1);
  629.     system1_draw_fg(bitmap,1);
  630.  
  631.     /* even if screen is off, sprites must still be drawn to update the collision table */
  632.     if (system1_video_mode & 0x10)  /* screen off */
  633.         fillbitmap(bitmap,palette_transparent_color,&Machine->drv->visible_area);
  634. }
  635.  
  636.  
  637.  
  638.  
  639.  
  640.  
  641.  
  642.  
  643.  
  644. WRITE_HANDLER( choplifter_scroll_x_w )
  645. {
  646.     system1_scrollx_ram[offset] = data;
  647.  
  648.     scrollx_row[offset/2] = (system1_scrollx_ram[offset & ~1] >> 1) + ((system1_scrollx_ram[offset | 1] & 1) << 7);
  649. }
  650.  
  651. void chplft_draw_bg(struct osd_bitmap *bitmap, int priority)
  652. {
  653.     int sx,sy,offs;
  654.     int choplifter_scroll_x_on = (system1_scrollx_ram[0] == 0xE5 && system1_scrollx_ram[1] == 0xFF) ? 0:1;
  655.  
  656.  
  657.     if (priority == -1)
  658.     {
  659.         /* optimized far background */
  660.  
  661.         /* for every character in the background video RAM, check if it has
  662.          * been modified since last time and update it accordingly.
  663.          */
  664.  
  665.         for (offs = 0;offs < system1_backgroundram_size;offs += 2)
  666.         {
  667.             if (bg_dirtybuffer[offs / 2])
  668.             {
  669.                 int code,color;
  670.  
  671.  
  672.                 bg_dirtybuffer[offs / 2] = 0;
  673.  
  674.                 code = (system1_backgroundram[offs] | (system1_backgroundram[offs+1] << 8));
  675.                 code = ((code >> 4) & 0x800) | (code & 0x7ff);    /* Heavy Metal only */
  676.                 color = ((code >> 5) & 0x3f) + 0x40;
  677.                 sx = (offs/2) % 32;
  678.                 sy = (offs/2) / 32;
  679.  
  680.                 drawgfx(bitmap1,Machine->gfx[0],
  681.                         code,
  682.                         color,
  683.                         0,0,
  684.                         8*sx,8*sy,
  685.                         0,TRANSPARENCY_NONE,0);
  686.             }
  687.         }
  688.  
  689.         /* copy the temporary bitmap to the screen */
  690.         if (choplifter_scroll_x_on)
  691.             copyscrollbitmap(bitmap,bitmap1,32,scrollx_row,0,0,&Machine->drv->visible_area,TRANSPARENCY_NONE,0);
  692.         else
  693.             copybitmap(bitmap,bitmap1,0,0,0,0,&Machine->drv->visible_area,TRANSPARENCY_NONE,0);
  694.     }
  695.  
  696.     else
  697.     {
  698.         priority <<= 3;
  699.  
  700.         for (offs = 0;offs < system1_backgroundram_size;offs += 2)
  701.         {
  702.             if ((system1_backgroundram[offs+1] & 0x08) == priority)
  703.             {
  704.                 int code,color;
  705.  
  706.  
  707.                 code = (system1_backgroundram[offs] | (system1_backgroundram[offs+1] << 8));
  708.                 code = ((code >> 4) & 0x800) | (code & 0x7ff);    /* Heavy Metal only */
  709.                 color = ((code >> 5) & 0x3f) + 0x40;
  710.                 sx = 8*((offs/2) % 32);
  711.                 sy = (offs/2) / 32;
  712.  
  713.                 if (choplifter_scroll_x_on)
  714.                     sx = (sx + scrollx_row[sy]) & 0xff;
  715.                 sy = 8*sy;
  716.  
  717.                 drawgfx(bitmap,Machine->gfx[0],
  718.                         code,
  719.                         color,
  720.                         0,0,
  721.                         sx,sy,
  722.                         &Machine->drv->visible_area,TRANSPARENCY_PEN,0);
  723.             }
  724.         }
  725.     }
  726. }
  727.  
  728. void choplifter_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
  729. {
  730.     int drawn;
  731.  
  732.  
  733.     system1_compute_palette();
  734.  
  735.     chplft_draw_bg(bitmap,-1);
  736.     drawn = system1_draw_fg(bitmap,0);
  737.     /* redraw low priority bg tiles if necessary */
  738.     if (drawn) chplft_draw_bg(bitmap,0);
  739.     DrawSprites(bitmap);
  740.     chplft_draw_bg(bitmap,1);
  741.     system1_draw_fg(bitmap,1);
  742.  
  743.     /* even if screen is off, sprites must still be drawn to update the collision table */
  744.     if (system1_video_mode & 0x10)  /* screen off */
  745.         fillbitmap(bitmap,palette_transparent_color,&Machine->drv->visible_area);
  746.  
  747.  
  748. #ifdef MAME_DEBUG
  749.     if (keyboard_pressed(KEYCODE_SPACE))        // goto next level
  750.     {
  751.         memory_region(REGION_CPU1)[0xC085]=33;
  752.     }
  753. #endif
  754. }
  755.  
  756.  
  757.  
  758. READ_HANDLER( wbml_bg_bankselect_r )
  759. {
  760.     return bg_bank_latch;
  761. }
  762.  
  763. WRITE_HANDLER( wbml_bg_bankselect_w )
  764. {
  765.     bg_bank_latch = data;
  766.     bg_bank = (data >> 1) & 0x03;    /* Select 4 banks of 4k, bit 2,1 */
  767. }
  768.  
  769. READ_HANDLER( wbml_paged_videoram_r )
  770. {
  771.     return bg_ram[0x1000*bg_bank + offset];
  772. }
  773.  
  774. WRITE_HANDLER( wbml_paged_videoram_w )
  775. {
  776.     bg_ram[0x1000*bg_bank + offset] = data;
  777. }
  778.  
  779. void wbml_backgroundrefresh(struct osd_bitmap *bitmap, int trasp)
  780. {
  781.     int page;
  782.  
  783.  
  784.     int xscroll = (bg_ram[0x7c0] >> 1) + ((bg_ram[0x7c1] & 1) << 7) - 256 + 5;
  785.     int yscroll = -bg_ram[0x7ba];
  786.  
  787.     for (page=0; page < 4; page++)
  788.     {
  789.         const unsigned char *source = bg_ram + (bg_ram[0x0740 + page*2] & 0x07)*0x800;
  790.         int startx = (page&1)*256+xscroll;
  791.         int starty = (page>>1)*256+yscroll;
  792.         int row,col;
  793.  
  794.  
  795.         for( row=0; row<32*8; row+=8 )
  796.         {
  797.             for( col=0; col<32*8; col+=8 )
  798.             {
  799.                 int code,priority;
  800.                 int x = (startx+col) & 0x1ff;
  801.                 int y = (starty+row) & 0x1ff;
  802.                 if (x > 256) x -= 512;
  803.                 if (y > 224) y -= 512;
  804.  
  805.  
  806.                 if (x > -8 && y > -8)
  807.                 {
  808.                     code = source[0] + (source[1] << 8);
  809.                     priority = code & 0x800;
  810.                     code = ((code >> 4) & 0x800) | (code & 0x7ff);
  811.  
  812.                     if (!trasp)
  813.                         drawgfx(bitmap,Machine->gfx[0],
  814.                                 code,
  815.                                 ((code >> 5) & 0x3f) + 64,
  816.                                 0,0,
  817.                                 x,y,
  818.                                 &Machine->drv->visible_area, TRANSPARENCY_NONE, 0);
  819.                     else if (priority)
  820.                         drawgfx(bitmap,Machine->gfx[0],
  821.                                 code,
  822.                                 ((code >> 5) & 0x3f) + 64,
  823.                                 0,0,
  824.                                 x,y,
  825.                                 &Machine->drv->visible_area, TRANSPARENCY_PEN, 0);
  826.                 }
  827.  
  828.                 source+=2;
  829.             }
  830.         }
  831.     } /* next page */
  832. }
  833.  
  834. void wbml_textrefresh(struct osd_bitmap *bitmap)
  835. {
  836.     int offs;
  837.  
  838.  
  839.     for (offs = 0;offs < 0x700;offs += 2)
  840.     {
  841.         int sx,sy,code;
  842.  
  843.  
  844.         sx = (offs/2) % 32;
  845.         sy = (offs/2) / 32;
  846.         code = bg_ram[offs] | (bg_ram[offs+1] << 8);
  847.         code = ((code >> 4) & 0x800) | (code & 0x7ff);
  848.  
  849.         drawgfx(bitmap,Machine->gfx[0],
  850.                 code,
  851.                 (code >> 5) & 0x3f,
  852.                 0,0,
  853.                 8*sx,8*sy,
  854.                 &Machine->drv->visible_area,TRANSPARENCY_PEN,0);
  855.     }
  856. }
  857.  
  858.  
  859. void wbml_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
  860. {
  861.     palette_recalc();
  862.     /* no need to check the return code since we redraw everything each frame */
  863.  
  864.     wbml_backgroundrefresh(bitmap,0);
  865.     DrawSprites(bitmap);
  866.     wbml_backgroundrefresh(bitmap,1);
  867.     wbml_textrefresh(bitmap);
  868.  
  869.     /* even if screen is off, sprites must still be drawn to update the collision table */
  870.     if (system1_video_mode & 0x10)  /* screen off */
  871.         fillbitmap(bitmap,palette_transparent_color,&Machine->drv->visible_area);
  872. }
  873.